#pragma once

#include <common.h>
#include <filesystem.h>
#include <windows.h>
#include <stdlib.h>

#define PASSWORD_PATH \
    HOSTEL_MANAGER_HOME_DIR "password"
#define PASSWORD_SIZE 8

HM_private
void input_password_(char const*const msg, char *const password) {
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    if (hStdin == INVALID_HANDLE_VALUE) {
        HM_throw(InternalError, "get console handle failed! please bug-report");
    }
    if (FlushConsoleInputBuffer(hStdin) == 0) {
        HM_throw(InternalError, "flush console input buffer failed!");
    }

restart:
    memset(password, 0, PASSWORD_SIZE + 1);
    printf("%s", msg);

    char chr = 0;
    DWORD cNumRead = 0;
    INPUT_RECORD irInBuf[PASSWORD_SIZE];
    unsigned int index = 0;
    while (true) {
        if (!ReadConsoleInputA(hStdin, irInBuf, PASSWORD_SIZE, &cNumRead)) {
            HM_throw(ReadConsoleInputFail, "read console input failed!");
        }

        for (size_t i = 0; i < cNumRead; ++i) {
            if (irInBuf[i].EventType != KEY_EVENT || !irInBuf[i].Event.KeyEvent.bKeyDown) {
                continue;
            }

            chr = irInBuf[i].Event.KeyEvent.uChar.AsciiChar;
            if ('!' <= chr && chr <= '~') {
                password[index++] = chr;
                putchar('*');
            }
            else if (chr == '\r') {
                goto complete;
            }
            else if (chr == '\b' && index > 0) {
                --index;
                printf("\b \b");
            }
            else if (chr != '\b') {
                puts("\nInvalidInput: You have typed a invalid character, please try again!");
                goto restart;
            }
            if (index > PASSWORD_SIZE) {
                puts("\nInvalidInput: The password is too long, please try again!");
                goto restart;
            }
        }
    }
complete:
    putchar('\n');
}

HM_private
void sign_up(void) {
    if (!crt_file_if_not_exist(PASSWORD_PATH)) {
        HM_throw(InternalError, "please bug-report");
    }

    char password[PASSWORD_SIZE + 1];
    char confirm_password[PASSWORD_SIZE + 1];
    puts("Welcome to hostel manager, please sign up first!");

    while (true) {
        input_password_("please type admin's password (max size is 8): ", password);
        input_password_("please type admin's password again: ", confirm_password);

        if (memcmp(password, confirm_password, 8) != 0) {
            puts("InvalidInput: The password is not the same!");
        } else {
            break;
        }
    }

    FILE* fp = fopen(PASSWORD_PATH, "w");
    fprintf(fp, "%s", password);
    fclose(fp);

    puts("sign up success! type `h` to get help");
}

HM_private
void login(void) {
    char typed_password[9];
    input_password_("please type admin's login password: ", typed_password);

    char password[9] = {0};
    FILE* fp = fopen(PASSWORD_PATH, "r");
    if (fp == NULL) {
        HM_throw(InternalError, "no password founded!");
    }
    fscanf(fp, "%s", password);
    fclose(fp);

    if (memcmp(typed_password, password, 8) != 0) {
        HM_throw(LoginFail, "the password is wrong!");
    }
    puts("login success! type `h` to get help");
}

#undef PASSWORD_PATH
#undef PASSWORD_SIZE
